iT邦幫忙

2021 iThome 鐵人賽

DAY 12
0
自我挑戰組

JavaScript 奇奇怪怪的核心觀念系列 第 12

(Day12) 物件,淺拷貝/深拷貝

  • 分享至 

  • xImage
  •  

前言

實作很常會遇到要讓物件複製出來,個別使用的狀況,在 JavaScript 物件複製分成兩種:

  • 淺拷貝
  • 深拷貝

淺拷貝(shallow copy)

這邊先來看看淺拷貝的範例:

var school = {
	name:'Taipei University',  
	classes: { 
		teacher: 'Alex',
		student:['Kevin','Clara','Rose']
        }
}
var newSchool = Object.assign({}, school)

這樣就是典型的淺拷貝,接者修改 newSchoolname 屬性看看:

var school = {
	name:'Taipei University',  
	classes: { 
		teacher: 'Alex',
		student:['Kevin','Clara','Rose']
	}
}
var newSchool = Object.assign({}, school)
newSchool.name = 'Taoyuan University'
console.log(school.name , newSchool.name)// 'Taipei University' , 'Taoyuan University'

可以發現 newSchoolname 確實獨立被修改了,不過要注意的是,這種淺拷貝方法只會對物件第一層的屬性生效,在第二層之下的仍然是上篇文章介紹的傳參考特性,這邊來看看修改第二層的範例:

var school = {
	name:'Taipei University',  
	classes: { 
		teacher: 'Alex',
		student:['Kevin','Clara','Rose']
	},
}
var newSchool = Object.assign({}, school)
newSchool.classes.teacher = 'Mary'
console.log(school.classes.teacher, newSchool.classes.teacher) // 'Mary', 'Mary'

可以發現第二層以下的屬性,兩個物件仍會按照傳參考特性一同被修改。

在原生 JS 中淺拷貝方法較多,其他還有:

  • 使用物件展開方法:
var school = {
	name:'Taipei University',  
	classes: { 
		teacher: 'Alex',
		student:['Kevin','Clara','Rose']
	},
}

var newSchool = { ...school }
newSchool.classes.teacher = 'Mary'
newSchool.name = 'Taoyuan University'
console.log(school.name , school.classes.teacher) //Taipei University Mary
  • for ... in 方法
var school = {
	name:'Taipei University',  
	classes: { 
		teacher: 'Alex',
		student:['Kevin','Clara','Rose']
	},
}
var newSchool = {}
for(var key in school ){
newSchool[key] = school[key]
}
newSchool.classes.teacher = 'Mary'
newSchool.name = 'Taoyuan University'
console.log(school.name , school.classes.teacher) //Taipei University Mary

不過實做中這種傳參考特性,有時反而達不到需求,這個時候就會想問了,JavaScript 中有沒有什麼方法,能複製兩個指向完全不同的物件?

而深拷貝就是能將物件記憶體指向完全分開的方法。

深拷貝(deep copy)

和淺拷貝不同,能夠做到深拷貝的功能,在原生 JavaScript 中只有一種寫法,如範例:

var school = {
	name:'Taipei University',  
	classes: { 
		teacher: 'Alex',
		student:['Kevin','Clara','Rose']
	},
}
var newSchool = JSON.parse(JSON.stringify(school ))
newSchool.classes.teacher = 'Mary'
console.log( school.classes.teacher, newSchool.classes.teacher) //Alex, Mary

看到 JSON.stringify() 其實就會明白,這個方法是先透過 JSON.stringify() 將物件轉成字串,再使用 JSON.parse() 將字串轉成物件,由於有先轉成字串因此兩個物件的記憶體是完全分開的。

參考資料

  • JavaScript 核心篇 (六角學院)

上一篇
(Day11) 物件參考特性
下一篇
(Day13) 函式基礎與參數介紹
系列文
JavaScript 奇奇怪怪的核心觀念30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言